import {
    request,
    encodeUrl,
    AbstractBookCrawler,
    BasicBook,
    SearchBookResult,
    Book,
    BasicChapter,
    BookCrawlerTest,
    BookSource, RequestOptions,
} from "../../common/common_node.js";

class BookCrawler extends AbstractBookCrawler {

    options = new RequestOptions({
        type: 'webView'
    });

    async searchBook(keyword, pageNum) {

        function getBoolList($) {
            const bookArr = [];
            const bookBoxArr = $("ul.txt-list:eq(0) li");
            bookBoxArr.each(function (index, elem) {
                if (index !== 0) {
                    let nameAndPath = $(this).find(".s2 a");
                    bookArr.push(new BasicBook({
                        name: nameAndPath.html(),
                        author: $(this).find(".s4").html(),
                        path: nameAndPath.attr("href"),
                    }));
                }
            })
            return bookArr;
        }

        let url = `${this.source.searchBaseUrl}/ar.php?keyWord=${encodeURIComponent(keyword)}`;
        const $ = await (await request(url, this.options)).doc();
        const bookArr = getBoolList($);

        return new SearchBookResult({
            pageNum: 1,
            pages: 1,
            keyword: keyword,
            bookList: bookArr,
        });
    }

    async bookDetails(path) {

        const $ = await (await request(this.source.bookBaseUrl + path, this.options)).doc();

        return new Book({
            name: $("meta[property='og:novel:book_name']").attr('content'),
            author: $("meta[property='og:novel:author']").attr('content'),
            path: path,
            intro: $("meta[property='og:description']").attr('content'),
            coverUrl: $("meta[property='og:image']").attr('content'),
            type: $("meta[property='og:novel:category']").attr('content'),
        });
    }

    async bookCatalog(path) {

        const options = this.options;

        async function fetchAndParseChapterInfo(pageUrl) {
            return request(pageUrl, options)
                .then((response) => response.text())
                .then((html) => {
                    return getChapterInfo(load(html));
                });
        }

        function getChapterInfo($) {
            let catalog = [];
            let chapters = $(".section-list").eq(1).find('li');
            chapters.each(function (i, elem) {
                const item = $(elem);
                catalog.push(new BasicChapter({
                    index: -1,
                    title: item.find('a').html(),
                    path: item.find('a').attr("href"),
                }));
            });
            return catalog;
        }


        const html = await (await request(this.source.bookBaseUrl + path, this.options)).text();
        const $ = load(html);
        const chapterPage = $('select[name="pageselect"] option');

        let urlArr = [];
        chapterPage.each(function (i, elem) {
            if (i !== 0) urlArr.push(this.source.bookBaseUrl + $(this).val())
        });
        //获取当前页面的章节
        let catalog = getChapterInfo($);

        //如果多页
        if (urlArr.length > 0) {
            const promises = urlArr.map((pageUrl) => fetchAndParseChapterInfo(pageUrl));
            let chapterInfos = await Promise.all(promises)
            for (const iterator of chapterInfos) {
                catalog.push(...iterator);
            }
        }
        let index = 0;
        for (const chapter of catalog) {
            chapter.index = index++;
        }
        return catalog;
    }

    async chapterContent(path) {

        const $ = await (await request(this.source.bookBaseUrl + path, this.options)).doc();
        //去除script
        let content = removeBasedOnSeparator(htmlToString($("#content").remove('script').html()), '\n', 0, true);

        let next = $(".m-bottom-opt a:eq(2)")
        if (next.text().includes("下一页")) {
            content = removeBasedOnSeparator(content, '\n', -1, false);
            content += await chapterContent(next.attr("href"));
        }
        return content;
    }
}

const source = {
    "id": "free_book_js/6",
    "name": "零点看书",
    "portalUrl": "http://www.aiquxs.la",
    "searchBaseUrl": "http://www.aiquxs.la",
    "bookBaseUrl": "http://www.aiquxs.la",
    "active": true
};

await new BookCrawlerTest(new BookCrawler(BookSource.createTestBookSource(source)), {
    enableSearch: true,
    keyword: "重生",
}).run();